From d6161e09cdfa662733e01d1a40cede50291743a5 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 1 Sep 2018 18:48:38 +0200 Subject: [PATCH] treelistmodel: Add more API to navigate the tree This adds functionality from GtkTreeIter into GtkTreeListRow that allows finding items in the model and getting their position for use in GtkListBox. --- gtk/gtktreelistmodel.c | 211 +++++++++++++++++++++++++++++++++++++---- gtk/gtktreelistmodel.h | 18 +++- 2 files changed, 207 insertions(+), 22 deletions(-) diff --git a/gtk/gtktreelistmodel.c b/gtk/gtktreelistmodel.c index 06a04af8c6..6904681c3e 100644 --- a/gtk/gtktreelistmodel.c +++ b/gtk/gtktreelistmodel.c @@ -28,8 +28,8 @@ enum { PROP_0, PROP_AUTOEXPAND, + PROP_MODEL, PROP_PASSTHROUGH, - PROP_ROOT_MODEL, NUM_PROPERTIES }; @@ -109,7 +109,7 @@ tree_node_get_nth_child (TreeNode *node, tree = node->children; child = gtk_css_rb_tree_get_root (tree); - while (TRUE) + while (child) { tmp = gtk_css_rb_tree_get_left (tree, child); if (tmp) @@ -131,7 +131,7 @@ tree_node_get_nth_child (TreeNode *node, child = gtk_css_rb_tree_get_right (tree, child); } - g_return_val_if_reached (NULL); + return NULL; } static guint @@ -649,12 +649,12 @@ gtk_tree_list_model_get_property (GObject *object, g_value_set_boolean (value, self->autoexpand); break; - case PROP_PASSTHROUGH: - g_value_set_boolean (value, self->passthrough); + case PROP_MODEL: + g_value_set_object (value, self->root_node.model); break; - case PROP_ROOT_MODEL: - g_value_set_object (value, self->root_node.model); + case PROP_PASSTHROUGH: + g_value_set_boolean (value, self->passthrough); break; default: @@ -696,6 +696,18 @@ gtk_tree_list_model_class_init (GtkTreeListModelClass *class) FALSE, GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + /** + * GtkTreeListModel:model: + * + * The root model displayed + */ + properties[PROP_MODEL] = + g_param_spec_object ("model", + P_("Model"), + P_("The root model displayed"), + G_TYPE_LIST_MODEL, + GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY); + /** * GtkTreeListModel:passthrough: * @@ -710,18 +722,6 @@ gtk_tree_list_model_class_init (GtkTreeListModelClass *class) FALSE, GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY); - /** - * GtkTreeListModel:root-model: - * - * The root model displayed - */ - properties[PROP_ROOT_MODEL] = - g_param_spec_object ("root-model", - P_("Root model"), - P_("The root model displayed"), - G_TYPE_LIST_MODEL, - GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY); - g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties); } @@ -773,6 +773,22 @@ gtk_tree_list_model_new (gboolean passthrough, return self; } +/** + * gtk_tree_list_model_get_model: + * @self: a #GtkTreeListModel + * + * Gets the root model that @self was created with. + * + * Returns: (transfer none): the root model + **/ +GListModel * +gtk_tree_list_model_get_model (GtkTreeListModel *self) +{ + g_return_val_if_fail (GTK_IS_TREE_LIST_MODEL (self), NULL); + + return self->root_node.model; +} + /** * gtk_tree_list_model_get_passthrough: * @self: a #GtkTreeListModel @@ -855,7 +871,9 @@ gtk_tree_list_model_get_autoexpand (GtkTreeListModel *self) * If @self is set to not be passthrough, this function is equivalent * to calling g_list_model_get_item(). * - * Returns: (nullable) (transfer: full): The row item + * Do not confuse this function with gtk_tree_list_model_get_child(). + * + * Returns: (nullable) (transfer full): The row item **/ GtkTreeListRow * gtk_tree_list_model_get_row (GtkTreeListModel *self, @@ -872,10 +890,41 @@ gtk_tree_list_model_get_row (GtkTreeListModel *self, return tree_node_get_row (node); } +/** + * gtk_tree_list_model_get_child: + * @self: a #GtkTreeListModel + * @position: position of the child to get + * + * Gets the row item corresponding to the child at index @position for + * @self's root model. + * + * If @position is greater than the number of children in the root model, + * %NULL is returned. + * + * Do not confuse this function with gtk_tree_list_model_get_row(). + * + * Returns: (nullable) (transfer full): the child in @position + **/ +GtkTreeListRow * +gtk_tree_list_model_get_child (GtkTreeListModel *self, + guint position) +{ + TreeNode *child; + + g_return_val_if_fail (GTK_IS_TREE_LIST_MODEL (self), NULL); + + child = tree_node_get_nth_child (&self->root_node, position); + if (child == NULL) + return NULL; + + return tree_node_get_row (child); +} + /*** ROW ***/ enum { ROW_PROP_0, + ROW_PROP_CHILDREN, ROW_PROP_DEPTH, ROW_PROP_EXPANDABLE, ROW_PROP_EXPANDED, @@ -932,6 +981,10 @@ gtk_tree_list_row_get_property (GObject *object, switch (prop_id) { + case ROW_PROP_CHILDREN: + g_value_set_object (value, gtk_tree_list_row_get_children (self)); + break; + case ROW_PROP_DEPTH: g_value_set_uint (value, gtk_tree_list_row_get_depth (self)); break; @@ -974,6 +1027,18 @@ gtk_tree_list_row_class_init (GtkTreeListRowClass *class) gobject_class->get_property = gtk_tree_list_row_get_property; gobject_class->dispose = gtk_tree_list_row_dispose; + /** + * GtkTreeListRow:children: + * + * The model holding the row's children. + */ + row_properties[ROW_PROP_CHILDREN] = + g_param_spec_object ("children", + P_("Children"), + P_("Model holding the row's children"), + G_TYPE_LIST_MODEL, + GTK_PARAM_READABLE); + /** * GtkTreeListRow:depth: * @@ -1030,6 +1095,26 @@ gtk_tree_list_row_init (GtkTreeListRow *self) { } +/** + * gtk_tree_list_row_get_position: + * @self: a #GtkTreeListRow + * + * Returns the position in the #GtkTreeListModel that @self occupies + * at the moment. + * + * Returns: The position in the model + **/ +guint +gtk_tree_list_row_get_position (GtkTreeListRow *self) +{ + g_return_val_if_fail (GTK_IS_TREE_LIST_ROW (self), 0); + + if (self->node == NULL) + return 0; + + return tree_node_get_position (self->node); +} + /** * gtk_tree_list_row_get_depth: * @self: a #GtkTreeListRow @@ -1110,6 +1195,7 @@ gtk_tree_list_row_set_expanded (GtkTreeListRow *self, } g_object_notify_by_pspec (G_OBJECT (self), row_properties[ROW_PROP_EXPANDED]); + g_object_notify_by_pspec (G_OBJECT (self), row_properties[ROW_PROP_CHILDREN]); } /** @@ -1194,3 +1280,88 @@ gtk_tree_list_row_get_item (GtkTreeListRow *self) return tree_node_get_item (self->node); } +/** + * gtk_tree_list_row_get_children: + * @self: a #GtkTreeListRow + * + * If the row is expanded, gets the model holding the children of @self. + * + * This model is the model created by the #GtkTreeListModelCreateModelFunc + * and contains the original items, no matter what value + * #GtkTreeListModel:passthrough is set to. + * + * Returns: (nullable) (transfer none): The model containing the children + **/ +GListModel * +gtk_tree_list_row_get_children (GtkTreeListRow *self) +{ + g_return_val_if_fail (GTK_IS_TREE_LIST_ROW (self), NULL); + + if (self->node == NULL) + return NULL; + + return self->node->model; +} + +/** + * gtk_tree_list_row_get_parent: + * @self: a #GtkTreeListRow + * + * Gets the row representing the parent for @self. That is the row that would + * need to be collapsed to make this row disappear. + * + * If @self is a row corresponding to the root model, %NULL is returned. + * + * The value returned by this function never changes until the + * row is destroyed. + * + * Returns: (nullable) (transfer full): The parent of @self + **/ +GtkTreeListRow * +gtk_tree_list_row_get_parent (GtkTreeListRow *self) +{ + TreeNode *parent; + + g_return_val_if_fail (GTK_IS_TREE_LIST_ROW (self), NULL); + + if (self->node == NULL) + return NULL; + + parent = self->node->parent; + if (parent->is_root) + return NULL; + + return tree_node_get_row (parent); +} + +/** + * gtk_tree_list_row_get_child: + * @self: a #GtkTreeListRow + * @position: position of the child to get + * + * If @self is not expanded or @position is greater than the number of + * children, %NULL is returned. + * + * Returns: (nullable) (transfer full): the child in @position + **/ +GtkTreeListRow * +gtk_tree_list_row_get_child (GtkTreeListRow *self, + guint position) +{ + TreeNode *child; + + g_return_val_if_fail (GTK_IS_TREE_LIST_ROW (self), NULL); + + if (self->node == NULL) + return NULL; + + if (self->node->children == NULL) + return NULL; + + child = tree_node_get_nth_child (self->node, position); + if (child == NULL) + return NULL; + + return tree_node_get_row (child); +} + diff --git a/gtk/gtktreelistmodel.h b/gtk/gtktreelistmodel.h index 344797be31..b282acfc85 100644 --- a/gtk/gtktreelistmodel.h +++ b/gtk/gtktreelistmodel.h @@ -49,6 +49,8 @@ GtkTreeListModel * gtk_tree_list_model_new (gboolean gpointer data, GDestroyNotify data_destroy); +GDK_AVAILABLE_IN_ALL +GListModel * gtk_tree_list_model_get_model (GtkTreeListModel *self); GDK_AVAILABLE_IN_ALL gboolean gtk_tree_list_model_get_passthrough (GtkTreeListModel *self); GDK_AVAILABLE_IN_ALL @@ -57,6 +59,9 @@ void gtk_tree_list_model_set_autoexpand (GtkTreeListMode GDK_AVAILABLE_IN_ALL gboolean gtk_tree_list_model_get_autoexpand (GtkTreeListModel *self); +GDK_AVAILABLE_IN_ALL +GtkTreeListRow * gtk_tree_list_model_get_child (GtkTreeListModel *self, + guint position); GDK_AVAILABLE_IN_ALL GtkTreeListRow * gtk_tree_list_model_get_row (GtkTreeListModel *self, guint position); @@ -64,14 +69,23 @@ GtkTreeListRow * gtk_tree_list_model_get_row (GtkTreeListMode GDK_AVAILABLE_IN_ALL gpointer gtk_tree_list_row_get_item (GtkTreeListRow *self); GDK_AVAILABLE_IN_ALL -guint gtk_tree_list_row_get_depth (GtkTreeListRow *self); -GDK_AVAILABLE_IN_ALL void gtk_tree_list_row_set_expanded (GtkTreeListRow *self, gboolean expanded); GDK_AVAILABLE_IN_ALL gboolean gtk_tree_list_row_get_expanded (GtkTreeListRow *self); GDK_AVAILABLE_IN_ALL gboolean gtk_tree_list_row_is_expandable (GtkTreeListRow *self); +GDK_AVAILABLE_IN_ALL +guint gtk_tree_list_row_get_position (GtkTreeListRow *self); +GDK_AVAILABLE_IN_ALL +guint gtk_tree_list_row_get_depth (GtkTreeListRow *self); +GDK_AVAILABLE_IN_ALL +GListModel * gtk_tree_list_row_get_children (GtkTreeListRow *self); +GDK_AVAILABLE_IN_ALL +GtkTreeListRow * gtk_tree_list_row_get_parent (GtkTreeListRow *self); +GDK_AVAILABLE_IN_ALL +GtkTreeListRow * gtk_tree_list_row_get_child (GtkTreeListRow *self, + guint child); G_END_DECLS -- 2.30.2